﻿--非战斗状态中允许shift+左键拖动目标头像
local function UnitFramesPlus_TargetPositionSet()
    TargetFrame:ClearAllPoints();
    TargetFrame:SetPoint("TOPLEFT", PlayerFrame, "TOPRIGHT", 45+96*UnitFramesPlusDB["player"]["scale"], 0);
    UnitFramesPlusVar["target"]["moved"] = 0;
end

function UnitFramesPlus_TargetPosition()
    if UnitFramesPlusVar["target"]["moved"] == 0 then
        if not InCombatLockdown() then
            UnitFramesPlus_TargetPositionSet();
        else
            local func = {};
            func.name = "UnitFramesPlus_TargetPositionSet";
            func.callback = function()
                UnitFramesPlus_TargetPositionSet();            
            end;
            UnitFramesPlus_WaitforCall(func);
        end
    end
end

local function UnitFramesPlus_TargetShiftDrag()
    TargetFrame:SetScript("OnMouseDown", function(self, elapsed)
        if UnitFramesPlusDB["target"]["movable"] == 1 then
            if IsShiftKeyDown() and (not InCombatLockdown()) then
                TargetFrame:StartMoving();
                UnitFramesPlusVar["target"]["moving"] = 1;
            end
        end
    end)

    TargetFrame:SetScript("OnMouseUp", function(self, elapsed)
        if UnitFramesPlusVar["target"]["moving"] == 1 then
            TargetFrame:StopMovingOrSizing();
            UnitFramesPlusVar["target"]["moving"] = 0;
            UnitFramesPlusVar["target"]["moved"] = 1;
        end
    end)

    TargetFrame:SetClampedToScreen(1);

    --更改目标头像默认位置以防止其和玩家扩展框重叠
    hooksecurefunc("UIParent_UpdateTopFramePositions", function()
        if (TargetFrame and not TargetFrame:IsUserPlaced()) then
            UnitFramesPlus_TargetPosition();
        end
    end)

    hooksecurefunc("TargetFrame_ResetUserPlacedPosition", function()
        UnitFramesPlusVar["target"]["moved"] = 0;
        UnitFramesPlus_TargetPosition();
    end)
end

--头像缩放
local function UnitFramesPlus_TargetFrameScaleSet(oldscale, newscale)
    local oldscale = oldscale or UnitFramesPlusDB["target"]["scale"];
    local newscale = newscale or UnitFramesPlusDB["target"]["scale"];
    local point, relativeTo, relativePoint, offsetX, offsetY = TargetFrame:GetPoint();
    TargetFrame:SetScale(newscale);
    TargetFrame:ClearAllPoints();
    TargetFrame:SetPoint(point, relativeTo, relativePoint, offsetX*oldscale/newscale, offsetY*oldscale/newscale);
    if UnitFramesPlusDB["target"]["portrait"] == 1 and UnitFramesPlusDB["target"]["ptype"] == 1 then
        UnitFramesPlus_TargetPortraitDisplayUpdate();
    end
end

function UnitFramesPlus_TargetFrameScale(oldscale, newscale)
    if not InCombatLockdown() then
        UnitFramesPlus_TargetFrameScaleSet(oldscale, newscale);
    else
        local func = {};
        func.name = "UnitFramesPlus_TargetFrameScaleSet";
        func.callback = function()
            UnitFramesPlus_TargetFrameScaleSet(oldscale, newscale);            
        end;
        UnitFramesPlus_WaitforCall(func);
    end
end

--目标生命值百分比
local TargetHPPct = CreateFrame("Frame", "UFP_TargetHPPct", TargetFrame);
TargetHPPct:SetWidth(45);
TargetHPPct:SetHeight(20);
TargetHPPct:ClearAllPoints();
TargetHPPct:SetPoint("RIGHT", TargetFrameHealthBar, "LEFT", -5, -1);
TargetHPPct.Text = TargetHPPct:CreateFontString("TargetHPPctText", "ARTWORK", "TextStatusBarText");
TargetHPPct.Text:SetAllPoints(TargetHPPct);
TargetHPPct.Text:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
TargetHPPct.Text:SetTextColor(1, 0.75, 0);
TargetHPPct.Text:SetJustifyH("RIGHT");
function UnitFramesPlus_TargetHealthPct()
    if UnitFramesPlusDB["target"]["hppct"] == 1 then
        UFP_TargetHPPct:RegisterEvent("PLAYER_TARGET_CHANGED");
        UFP_TargetHPPct:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", "target");
        UFP_TargetHPPct:SetScript("OnEvent", function(self, event, ...)
            if UnitExists("target") then
                UnitFramesPlus_TargetHealthPctDisplayUpdate();
            end
        end)
    else
        UFP_TargetHPPct.Text:SetText("");
        if UFP_TargetHPPct:IsEventRegistered("PLAYER_TARGET_CHANGED") then
            UFP_TargetHPPct:UnregisterEvent("PLAYER_TARGET_CHANGED");
            UFP_TargetHPPct:UnregisterEvent("UNIT_HEALTH_FREQUENT");
            UFP_TargetHPPct:SetScript("OnEvent", nil);
        end
    end
end

--刷新目标生命值百分比显示
function UnitFramesPlus_TargetHealthPctDisplayUpdate()
    local PctText = "";
    if UnitFramesPlusDB["target"]["hppct"] == 1 then
        local CurHP = UnitHealth("target");
        local MaxHP = UnitHealthMax("target");
        if MaxHP > 0 then
            PctText = math.floor(100*CurHP/MaxHP).."%";
        end
    end
    UFP_TargetHPPct.Text:SetText(PctText);
end

--目标法力值百分比
local TargetMPPct = CreateFrame("Frame", "UFP_TargetMPPct", TargetFrame);
TargetMPPct:SetWidth(45);
TargetMPPct:SetHeight(20);
TargetMPPct:ClearAllPoints();
TargetMPPct:SetPoint("RIGHT", TargetFrameManaBar, "LEFT", -5, -1);
TargetMPPct.Text = TargetMPPct:CreateFontString("TargetMPPctText", "ARTWORK", "TextStatusBarText");
TargetMPPct.Text:SetAllPoints(TargetMPPct);
TargetMPPct.Text:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
TargetMPPct.Text:SetTextColor(1, 1, 1);
TargetMPPct.Text:SetJustifyH("RIGHT");
function UnitFramesPlus_TargetManaPct()
    if UnitFramesPlusDB["target"]["mppct"] == 1 then
        UFP_TargetMPPct:RegisterEvent("PLAYER_TARGET_CHANGED");
        UFP_TargetMPPct:RegisterUnitEvent("UNIT_POWER", "target");
        UFP_TargetMPPct:SetScript("OnEvent", function(self, event, ...)
            if UnitExists("target") then
                UnitFramesPlus_TargetManaPctDisplayUpdate();
            end
        end)
    else
        UFP_TargetMPPct.Text:SetText("");
        if UFP_TargetMPPct:IsEventRegistered("UNIT_POWER") then
            UFP_TargetMPPct:UnregisterEvent("PLAYER_TARGET_CHANGED");
            UFP_TargetMPPct:UnregisterEvent("UNIT_POWER");
            UFP_TargetMPPct:SetScript("OnEvent", nil);
        end
    end
end

--刷新目标法力值百分比显示
function UnitFramesPlus_TargetManaPctDisplayUpdate()
    if UnitFramesPlusDB["target"]["mppct"] == 1 then
        local MPPct = "";
        local CurMP = UnitPower("target");
        local MaxMP = UnitPowerMax("target");
        local powerType = UnitPowerType("target");
        if powerType == 0 then
            if MaxMP > 0 then
                MPPct = math.floor(100*CurMP/MaxMP).."%";
            end
        end
        UFP_TargetMPPct.Text:SetText(MPPct);
    end
end

--目标生命条染色
local chb = CreateFrame("Frame");
function UnitFramesPlus_TargetColorHPBar()
    if UnitFramesPlusDB["target"]["colorhp"] == 1 then
        if UnitFramesPlusDB["target"]["colortype"] == 1 then
            TargetFrameHealthBar:SetScript("OnValueChanged", nil);
            chb:RegisterEvent("PLAYER_TARGET_CHANGED");
            chb:SetScript("OnEvent", function(self, event, ...)
                if UnitExists("target") then
                    UnitFramesPlus_TargetColorHPBarDisplayUpdate();
                end
            end)
        elseif UnitFramesPlusDB["target"]["colortype"] == 2 then
            if chb:IsEventRegistered("PLAYER_TARGET_CHANGED") then
                chb:UnregisterEvent("PLAYER_TARGET_CHANGED");
                chb:SetScript("OnEvent", nil);
            end
            TargetFrameHealthBar:SetScript("OnValueChanged", function(self, value)
                UnitFramesPlus_TargetColorHPBarDisplayUpdate();
            end)
        end
        --TargetFrameHealthBar.lockColor = true;
    else
        TargetFrameHealthBar:SetScript("OnValueChanged", nil);
        if chb:IsEventRegistered("PLAYER_TARGET_CHANGED") then
            chb:UnregisterEvent("PLAYER_TARGET_CHANGED");
            chb:SetScript("OnEvent", nil);
        end
        TargetFrameHealthBar:SetStatusBarColor(0, 1, 0);
        --TargetFrameHealthBar.lockColor = nil;
    end
end

--刷新目标生命条染色显示
function UnitFramesPlus_TargetColorHPBarDisplayUpdate()
    if UnitFramesPlusDB["target"]["colorhp"] == 1 then
        if UnitFramesPlusDB["target"]["colortype"] == 1 then
            local HealthBarColor = {r=0, g=1, b=0};
            if UnitIsPlayer("target") then
                HealthBarColor = RAID_CLASS_COLORS[select(2, UnitClass("target"))] or {r=0, g=1, b=0};
            end
            TargetFrameHealthBar:SetStatusBarColor(HealthBarColor.r, HealthBarColor.g, HealthBarColor.b);
        elseif UnitFramesPlusDB["target"]["colortype"] == 2 then
            local CurHP = UnitHealth("target");
            local MaxHP = UnitHealthMax("target");
            local Pct = math.floor(100*CurHP/MaxHP)/100;
            local r, g, b = 0, 1, 0;
            if Pct > 0.5 then
                r = (1.0-Pct)*2;
                g = 1.0;
            else
                r = 1.0;
                g = Pct*2;
            end
            if r < 0 then r = 0 end
            if g < 0 then g = 0 end
            if r > 1 then r = 1 end
            if g > 1 then g = 1 end
            TargetFrameHealthBar:SetStatusBarColor(r, g, b);
        end
    end
end

--目标种族或类型
local TargetType = TargetFrame:CreateFontString("UFP_TargetType", "ARTWORK", "TextStatusBarText");
TargetType:ClearAllPoints();
TargetType:SetPoint("BOTTOMLEFT", TargetFrameNameBackground, "TOPLEFT", 6, 2);
TargetType:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
TargetType:SetTextColor(1, 0.75, 0);

local TargetRace = TargetFrame:CreateFontString("UFP_TargetRace", "ARTWORK", "TextStatusBarText");
TargetRace:ClearAllPoints();
TargetRace:SetPoint("BOTTOMLEFT", TargetFrameNameBackground, "TOPLEFT", 6, 2);
TargetRace:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
TargetRace:SetTextColor(1, 0.75, 0);

local tr = CreateFrame("Frame");
function UnitFramesPlus_TargetRace()
    if UnitFramesPlusDB["target"]["race"] == 1 then
        tr:RegisterEvent("PLAYER_TARGET_CHANGED");
        tr:SetScript("OnEvent", function(self, event)
            if UnitExists("target") then
                UnitFramesPlus_TargetRaceDisplayUpdate();
            end
        end)
    else
        UFP_TargetType:SetText("");
        UFP_TargetRace:SetText("");
        if tr:IsEventRegistered("PLAYER_TARGET_CHANGED") then
            tr:UnregisterEvent("PLAYER_TARGET_CHANGED");
            tr:SetScript("OnEvent", nil);
        end
    end
end

--刷新目标种族或类型显示
function UnitFramesPlus_TargetRaceDisplayUpdate()
    local typeText = "";
    local raceText = "";
    if UnitFramesPlusDB["target"]["race"] == 1 then
        if UnitIsPlayer("target") then
            raceText = UnitRace("target");
        elseif UnitCreatureType("target") then
            typeText = UnitCreatureType("target");
        end
    end
    UFP_TargetType:SetText(typeText);
    UFP_TargetRace:SetText(raceText);
end


--目标职业图标
local ClassIcon = CreateFrame("Button", "UFP_TargetClassIcon", TargetFrame);
ClassIcon:SetWidth(32);
ClassIcon:SetHeight(32);
ClassIcon:ClearAllPoints();
ClassIcon:SetPoint("TOPLEFT", TargetFrame, "TOPLEFT", 119, 3);
ClassIcon:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight");
ClassIcon:SetAlpha(0);

ClassIcon.Border = ClassIcon:CreateTexture("UFP_TargetClassIconBorder", "OVERLAY");
ClassIcon.Border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder");
ClassIcon.Border:SetWidth(54);
ClassIcon.Border:SetHeight(54);
ClassIcon.Border:SetPoint("CENTER", 11, -12);

ClassIcon.Background = ClassIcon:CreateTexture("UFP_TargetClassIconBG", "BORDER");
ClassIcon.Background:SetTexture("Interface\\Minimap\\UI-Minimap-Background");
ClassIcon.Background:SetWidth(20);
ClassIcon.Background:SetHeight(20);
ClassIcon.Background:SetPoint("CENTER");
ClassIcon.Background:SetVertexColor(0, 0, 0, 1);

ClassIcon.Icon = ClassIcon:CreateTexture("UFP_TargetClassIconIcon", "ARTWORK");
ClassIcon.Icon:SetTexture("Interface\\WorldStateFrame\\Icons-Classes");
ClassIcon.Icon:SetWidth(20);
ClassIcon.Icon:SetHeight(20);
ClassIcon.Icon:SetPoint("CENTER");

local tci = CreateFrame("Frame");
function UnitFramesPlus_TargetClassIcon()
    if UnitFramesPlusDB["target"]["classicon"] == 1 then
        tci:RegisterEvent("PLAYER_TARGET_CHANGED");
        tci:SetScript("OnEvent", function(self, event)
            if UnitExists("target") then
                UnitFramesPlus_TargetClassIconDisplayUpdate();
            end
        end)
    else
        UFP_TargetClassIcon:SetAlpha(0);
        if tci:IsEventRegistered("PLAYER_TARGET_CHANGED") then
            tci:UnregisterEvent("PLAYER_TARGET_CHANGED");
            tci:SetScript("OnEvent", nil);
        end
    end
end

--刷新目标职业图标显示
function UnitFramesPlus_TargetClassIconDisplayUpdate()
    if UnitFramesPlusDB["target"]["classicon"] == 1 then
        if UnitIsPlayer("target") then
            local IconCoord = CLASS_ICON_TCOORDS[select(2,UnitClass("target"))];
            if IconCoord then
                UFP_TargetClassIcon.Icon:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles");
                UFP_TargetClassIcon.Icon:SetTexCoord(unpack(IconCoord));
            end
            UFP_TargetClassIcon:SetAlpha(1);
        else
            UFP_TargetClassIcon:SetAlpha(0);
        end
    else
        UFP_TargetClassIcon:SetAlpha(0);
    end
end

--目标职业图标扩展：左键观察/右键交易/中键密语/四号键跟随
local isclicked = false

local function TargetClassIconDown()
    local point, relativeTo, relativePoint, offsetX, offsetY = UFP_TargetClassIcon.Icon:GetPoint();
    UFP_TargetClassIcon.Icon:ClearAllPoints();
    UFP_TargetClassIcon.Icon:SetPoint(point, relativeTo, relativePoint, offsetX+1, offsetY-1);
    return true;
end

UFP_TargetClassIcon:SetScript("OnMouseDown", function(self, button)
    if UnitFramesPlusDB["target"]["moreaction"] == 1 then
        if (not UnitCanAttack("player", "target")) and UnitIsPlayer("target") then
            if button == "LeftButton" then
                if CheckInteractDistance("target", 1) then
                    isclicked = TargetClassIconDown();
                    InspectUnit("target");
                end
            elseif button == "RightButton" then
                if CheckInteractDistance("target", 2) then
                    isclicked = TargetClassIconDown();
                    InitiateTrade("target");
                end
            elseif button == "MiddleButton" then
                isclicked = TargetClassIconDown();
                local server = nil;
                local name, server = UnitName("target");
                local fullname = name;
                if server and (not "target" or UnitIsSameServer("player", "target") ~= 1) then
                    fullname = name.."-"..server;
                end
                ChatFrame_SendTell(fullname);
            elseif button == "Button4" then
                if CheckInteractDistance("target",4) then
                    isclicked = TargetClassIconDown();
                    local server = nil;
                    local name, server = UnitName("target");
                    local fullname = name;
                    if server and (not "target" or UnitIsSameServer("player", "target") ~= 1) then
                        fullname = name.."-"..server;
                    end
                    FollowUnit(fullname, 1);
                end
            end
        end
    end
end)

local function TargetClassIconUp()
    local point, relativeTo, relativePoint, offsetX, offsetY = UFP_TargetClassIcon.Icon:GetPoint();
    UFP_TargetClassIcon.Icon:ClearAllPoints();
    UFP_TargetClassIcon.Icon:SetPoint(point, relativeTo, relativePoint, offsetX-1, offsetY+1);
    return false;
end

UFP_TargetClassIcon:SetScript("OnMouseUp", function(self)
    if UnitFramesPlusDB["target"]["moreaction"] == 1 and isclicked then
        isclicked = TargetClassIconUp();
    end
end)

--目标头像内战斗信息
local TargetPortraitIndicator = CreateFrame("Frame", "UFP_TargetPortraitIndicator", TargetFrame);
TargetPortraitIndicator:CreateFontString("UFP_TargetHitIndicator", "OVERLAY", "NumberFontNormalHuge");
UFP_TargetHitIndicator:ClearAllPoints();
UFP_TargetHitIndicator:SetPoint("CENTER", TargetFramePortrait, "CENTER", 0, 0);
CombatFeedback_Initialize(TargetPortraitIndicator, UFP_TargetHitIndicator, 28);
function UnitFramesPlus_TargetPortraitIndicator()
    if UnitFramesPlusDB["target"]["indicator"] == 1 then
        UFP_TargetPortraitIndicator:RegisterEvent("PLAYER_TARGET_CHANGED");
        UFP_TargetPortraitIndicator:RegisterUnitEvent("UNIT_COMBAT", "target");
        UFP_TargetPortraitIndicator:SetScript("OnEvent", function(self, event, ...)
            if event == "PLAYER_TARGET_CHANGED" then
                UFP_TargetHitIndicator:Hide();
            elseif event == "UNIT_COMBAT" then
                local arg1, arg2, arg3, arg4, arg5 = ...;
                CombatFeedback_OnCombatEvent(self, arg2, arg3, arg4, arg5);
            end
        end)

        UFP_TargetPortraitIndicator:SetScript("OnUpdate", function(self, elapsed)
            CombatFeedback_OnUpdate(self, elapsed);
        end)
    else
        UFP_TargetHitIndicator:Hide();
        if UFP_TargetPortraitIndicator:IsEventRegistered("UNIT_COMBAT") then
            UFP_TargetPortraitIndicator:UnregisterEvent("PLAYER_TARGET_CHANGED");
            UFP_TargetPortraitIndicator:UnregisterEvent("UNIT_COMBAT");
            UFP_TargetPortraitIndicator:SetScript("OnEvent", nil);
            UFP_TargetPortraitIndicator:SetScript("OnUpdate", nil);
        end
    end
end

--改变目标buff/debuff图标大小
local function TargetBuffSize(self, auraName, numAuras, numOppositeAuras, largeAuraList, updateFunc, maxRowWidth, offsetX, mirrorAurasVertically)
    local UFP_AURA_OFFSET_Y = 3;
    local UFP_LARGE_AURA_SIZE, UFP_SMALL_AURA_SIZE;
    if UnitFramesPlusDB["target"]["buffsize"] == 1 then
        UFP_LARGE_AURA_SIZE = UnitFramesPlusDB["target"]["mysize"];
        UFP_SMALL_AURA_SIZE = UnitFramesPlusDB["target"]["othersize"];
    else
        UFP_LARGE_AURA_SIZE = 21;
        UFP_SMALL_AURA_SIZE = 17;
    end
    local UFP_AURA_ROW_WIDTH = 122;
    local UFP_NUM_TOT_AURA_ROWS = 2;

    local UFP_SIZE;
    local UFP_OFFSETY = UFP_AURA_OFFSET_Y;
    local UFP_ROWWIDTH = 0;
    local UFP_FIRSTBUFFONROW = 1;
    for i=1, numAuras, 1 do
        if ( largeAuraList[i] ) then
            UFP_SIZE = UFP_LARGE_AURA_SIZE;
            UFP_OFFSETY = UFP_AURA_OFFSET_Y + UFP_AURA_OFFSET_Y;
        else
            UFP_SIZE = UFP_SMALL_AURA_SIZE;
        end
        if ( i == 1 ) then
            UFP_ROWWIDTH = UFP_SIZE;
            self.auraRows = self.auraRows + 1;
        else
            UFP_ROWWIDTH = UFP_ROWWIDTH + UFP_SIZE + offsetX;
        end
        if ( UFP_ROWWIDTH > maxRowWidth ) then
            updateFunc(self, auraName, i, numOppositeAuras, UFP_FIRSTBUFFONROW, UFP_SIZE, offsetX, UFP_OFFSETY, mirrorAurasVertically);
            UFP_ROWWIDTH = UFP_SIZE;
            self.auraRows = self.auraRows + 1;
            UFP_FIRSTBUFFONROW = i;
            UFP_OFFSETY = UFP_AURA_OFFSET_Y;
            --if ( self.auraRows > UFP_NUM_TOT_AURA_ROWS ) or ( self.auraRows > 2 ) then
            if ( self.auraRows > UFP_NUM_TOT_AURA_ROWS ) then
                maxRowWidth = UFP_AURA_ROW_WIDTH;
            end
        else
            updateFunc(self, auraName, i, numOppositeAuras, i - 1, UFP_SIZE, offsetX, UFP_OFFSETY, mirrorAurasVertically);
        end
    end
end

function UnitFramesPlus_TargetBuffSize()
    hooksecurefunc("TargetFrame_UpdateAuraPositions", TargetBuffSize);
end

--目标头像
local Target3DPortrait = CreateFrame("PlayerModel", "UFP_Target3DPortrait", TargetFrame);
Target3DPortrait:SetWidth(50);
Target3DPortrait:SetHeight(50);
Target3DPortrait:SetFrameLevel(1);
Target3DPortrait:ClearAllPoints();
Target3DPortrait:SetPoint("CENTER", TargetFramePortrait, "CENTER", -1, -1);
Target3DPortrait:Hide();
Target3DPortrait.Background = Target3DPortrait:CreateTexture("UFP_Target3DPortraitBG", "BACKGROUND");
Target3DPortrait.Background:SetTexture("Interface\\AddOns\\UnitFramesPlus\\Portrait3D");
Target3DPortrait.Background:SetWidth(64);
Target3DPortrait.Background:SetHeight(64);
Target3DPortrait.Background:ClearAllPoints();
Target3DPortrait.Background:SetPoint("CENTER", Target3DPortrait, "CENTER", 0, 0);
Target3DPortrait.Background:Hide();

local TargetClassPortrait = TargetFrame:CreateTexture("UFP_TargetClassPortrait", "ARTWORK");
TargetClassPortrait:SetWidth(64);
TargetClassPortrait:SetHeight(64);
TargetClassPortrait:ClearAllPoints();
TargetClassPortrait:SetPoint("TOPRIGHT", TargetFrame, "TOPRIGHT", -42, -12);
TargetClassPortrait:Hide();

local tpt = CreateFrame("Frame");
function UnitFramesPlus_TargetPortrait()
    if UnitFramesPlusDB["target"]["portrait"] == 1 then
        TargetFramePortrait:Hide();
        if UnitFramesPlusDB["target"]["ptype"] == 1 then
            UFP_Target3DPortrait:Show();
            UFP_TargetClassPortrait:Hide();
            UnitFramesPlus_TargetPortrait3DBGDisplayUpdate();
            tpt:RegisterEvent("PLAYER_TARGET_CHANGED");
            tpt:RegisterUnitEvent("UNIT_MODEL_CHANGED", "target");
            tpt:RegisterUnitEvent("UNIT_CONNECTION", "target");
            tpt:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", "target");
            tpt:SetScript("OnEvent", function(self, event, ...)
                if event == "PLAYER_TARGET_CHANGED" then
                    if UnitExists("target") then
                        if UnitFramesPlusDB["target"]["p3dbg"] == 1 then
                            local color = RAID_CLASS_COLORS[select(2, UnitClass("target"))] or NORMAL_FONT_COLOR;
                            UFP_Target3DPortrait.Background:SetVertexColor(color.r/1.5, color.g/1.5, color.b/1.5, 1);
                        end
                        UnitFramesPlus_TargetPortraitDisplayUpdate();
                    end
                elseif event == "UNIT_MODEL_CHANGED" or event == "UNIT_CONNECTION" then
                    UnitFramesPlus_TargetPortraitDisplayUpdate();
                elseif event == "UNIT_HEALTH_FREQUENT" then
                    if (not UnitIsConnected("target")) or UnitIsGhost("target") then
                        UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 0.25, 0.25, 0.25);
                    elseif UnitIsDead("target") then
                        UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 0.3, 0.3);
                    else
                        UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 1, 1);
                    end
                end
            end)
        elseif UnitFramesPlusDB["target"]["ptype"] == 2 then
            UFP_Target3DPortrait:Hide();
            UFP_TargetClassPortrait:Show();
            if not tpt:IsEventRegistered("PLAYER_TARGET_CHANGED") then
                tpt:RegisterEvent("PLAYER_TARGET_CHANGED");
            else
                if tpt:IsEventRegistered("UNIT_MODEL_CHANGED") then
                    tpt:UnregisterEvent("UNIT_MODEL_CHANGED");
                    tpt:UnregisterEvent("UNIT_CONNECTION");
                    tpt:UnregisterEvent("UNIT_HEALTH_FREQUENT");
                end
            end
            tpt:SetScript("OnEvent", function(self, event, ...)
                if event == "PLAYER_TARGET_CHANGED" then
                    if UnitExists("target") then
                        UnitFramesPlus_TargetPortraitDisplayUpdate();
                    end
                end
            end)
        end
        UnitFramesPlus_TargetPortraitDisplayUpdate();
    else
        TargetFramePortrait:Show();
        UFP_Target3DPortrait:Hide();
        UFP_TargetClassPortrait:Hide();
        if tpt:IsEventRegistered("PLAYER_TARGET_CHANGED") then
            tpt:UnregisterEvent("PLAYER_TARGET_CHANGED");
            tpt:UnregisterEvent("UNIT_MODEL_CHANGED");
            tpt:UnregisterEvent("UNIT_CONNECTION");
            tpt:UnregisterEvent("UNIT_HEALTH_FREQUENT");
            tpt:SetScript("OnEvent", nil);
        end
    end
end

--刷新目标头像显示
function UnitFramesPlus_TargetPortraitDisplayUpdate()
    if UnitFramesPlusDB["target"]["ptype"] == 1 then
        if (not UnitIsConnected("target")) or (not UnitIsVisible("target")) then
            UFP_Target3DPortrait:SetPortraitZoom(0);
            UFP_Target3DPortrait:SetCamDistanceScale(0.25);
            UFP_Target3DPortrait:SetPosition(0,0,0.5);
            UFP_Target3DPortrait:ClearModel();
            UFP_Target3DPortrait:SetModel("Interface\\Buttons\\TalkToMeQuestionMark.M2");
        else
            UFP_Target3DPortrait:SetPortraitZoom(1);
            UFP_Target3DPortrait:SetCamDistanceScale(1);
            UFP_Target3DPortrait:SetPosition(0,0,0);
            UFP_Target3DPortrait:ClearModel();
            UFP_Target3DPortrait:SetUnit("target");
            if (not UnitIsConnected("target")) or UnitIsGhost("target") then
                UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 0.25, 0.25, 0.25);
            elseif UnitIsDead("target") then
                UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 0.3, 0.3);
            else
                UFP_Target3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 1, 1);
            end
        end
    elseif UnitFramesPlusDB["target"]["ptype"] == 2 then
        if UnitFramesPlusDB["target"]["npcno"] == 1 and not UnitIsPlayer("target") then
            if UFP_TargetClassPortrait:IsShown() then
                TargetFramePortrait:Show();
                UFP_TargetClassPortrait:Hide();
            end
        else
            if TargetFramePortrait:IsShown() then
                TargetFramePortrait:Hide();
                UFP_TargetClassPortrait:Show();
            end
            local IconCoord = CLASS_ICON_TCOORDS[select(2,UnitClass("target"))]
            if IconCoord then
                UFP_TargetClassPortrait:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles");
                UFP_TargetClassPortrait:SetTexCoord(unpack(IconCoord));
            end
        end
    end
end

--刷新目标3D头像背景显示
function UnitFramesPlus_TargetPortrait3DBGDisplayUpdate()
    if UnitFramesPlusDB["target"]["portrait"] == 1 
    and UnitFramesPlusDB["target"]["ptype"] == 1
    and UnitFramesPlusDB["target"]["p3dbg"] == 1 then
        UFP_Target3DPortrait.Background:Show();
    else
        UFP_Target3DPortrait.Background:Hide();
    end
end

--鼠标移过时才显示数值
function UnitFramesPlus_TargetBarTextMouseShow()
    if UnitFramesPlusDB["target"]["mouseshow"] == 1 then
        TargetFrameTextureFrameHealthBarText:SetAlpha(0);
        TargetFrameTextureFrameHealthBarTextLeft:SetAlpha(0);
        TargetFrameTextureFrameHealthBarTextRight:SetAlpha(0);
        TargetFrameHealthBar:SetScript("OnEnter",function(self)
            TargetFrameTextureFrameHealthBarText:SetAlpha(1);
            TargetFrameTextureFrameHealthBarTextLeft:SetAlpha(1);
            TargetFrameTextureFrameHealthBarTextRight:SetAlpha(1);
        end);
        TargetFrameHealthBar:SetScript("OnLeave",function()
            TargetFrameTextureFrameHealthBarText:SetAlpha(0);
            TargetFrameTextureFrameHealthBarTextLeft:SetAlpha(0);
            TargetFrameTextureFrameHealthBarTextRight:SetAlpha(0);
        end);
        TargetFrameTextureFrameManaBarText:SetAlpha(0);
        TargetFrameTextureFrameManaBarTextLeft:SetAlpha(0);
        TargetFrameTextureFrameManaBarTextRight:SetAlpha(0);
        TargetFrameManaBar:SetScript("OnEnter",function(self)
            TargetFrameTextureFrameManaBarText:SetAlpha(1);
            TargetFrameTextureFrameManaBarTextLeft:SetAlpha(1);
            TargetFrameTextureFrameManaBarTextRight:SetAlpha(1);
        end);
        TargetFrameManaBar:SetScript("OnLeave",function()
            TargetFrameTextureFrameManaBarText:SetAlpha(0);
            TargetFrameTextureFrameManaBarTextLeft:SetAlpha(0);
            TargetFrameTextureFrameManaBarTextRight:SetAlpha(0);
        end);
    else
        TargetFrameTextureFrameHealthBarText:SetAlpha(1);
        TargetFrameTextureFrameHealthBarTextLeft:SetAlpha(1);
        TargetFrameTextureFrameHealthBarTextRight:SetAlpha(1);
        TargetFrameHealthBar:SetScript("OnEnter",nil);
        TargetFrameHealthBar:SetScript("OnLeave",nil);
        TargetFrameTextureFrameManaBarText:SetAlpha(1);
        TargetFrameTextureFrameManaBarTextLeft:SetAlpha(1);
        TargetFrameTextureFrameManaBarTextRight:SetAlpha(1);
        TargetFrameManaBar:SetScript("OnEnter",nil);
        TargetFrameManaBar:SetScript("OnLeave",nil);
    end
end

local function UnitFramesPlus_SysToT()
    if UnitFramesPlusDB["target"]["systot"] == 1 then
        if tonumber(GetCVar("showTargetOfTarget")) == 1 then
            SetCVar("showTargetOfTarget", 0, 1);
        end
    end
end

--模块初始化
function UnitFramesPlus_TargetInit()
    UnitFramesPlus_TargetShiftDrag();
    UnitFramesPlus_TargetHealthPct();
    UnitFramesPlus_TargetManaPct();
    UnitFramesPlus_TargetRace();
    UnitFramesPlus_TargetClassIcon();
    UnitFramesPlus_TargetPortraitIndicator();
    UnitFramesPlus_TargetColorHPBar();
    UnitFramesPlus_TargetBuffSize();
    UnitFramesPlus_TargetPortrait();
    UnitFramesPlus_TargetBarTextMouseShow();
end

function UnitFramesPlus_TargetLayout()
    UnitFramesPlus_TargetPosition();
    UnitFramesPlus_TargetFrameScale();
end

function UnitFramesPlus_TargetCvar()
    UnitFramesPlus_SysToT();
end
